/*
STL萃取与模板偏特化
用于迭代器与算法的接口规范
*/

//一般STL算法传递的参数为迭代器，如下
template<class T>
void _stl_printf1(T Iter)//传入一个迭代器
{};

//有时候我们需要用到迭代器所指的数据类型，比如用它创建变量，可以用模板参数函数自动推导
template<class A,class B>
void _stl_printf2(A Iter1,B Iter2)//模板B就是迭代器指向的数据类型
{
    B temp;//通过B可以创建迭代器所指类型的变量
    /*  */
}
template<class T>
void _stl_printf3(T Iter)
{
    _stl_printf2(Iter,*Iter);//传入迭代器的解指针
}

//当迭代器所指的数据类型作为返回值类型的时候，就无法通过自动推导了，但可以用自定内嵌数值类型
//一般迭代器都会自己定义一个value_type，方便算法的操作可以直接定义所指数据类型的变量，如
template<class T>
class Iterator
{
public:
    typedef T value_type;
    /*  */
};

//迭代器指向类型做返回值时
template<class T>
typename T::value_type _stl_printf4(T Iter)//加typename告诉编译器T::value_type是一个数据类型
{
    T::value_type temp;//通过迭代器的内嵌value_type，创建需要的数据类型，不再需要另一个函数推导
    /*  */
}

/*
但是STL规则声明，STL算法需要兼容原生指针，毕竟迭代器本质也是一种特殊的指针
对于STL算法，传容器的迭代器能实现功能，传原生指针也要实现功能，如传int*之类的原生指针
算法中的T::value_type temp，当传来的参数是迭代器时，正确，因为迭代器中声明了内嵌value_type
传的是原生指针时，出错，因为不存在int*::value_type，int是基础数据类型，不会内嵌value_type
因此算法设计上会存在不兼容原生指针的问题，于是出现traits萃取技术
*/

//泛型版本，用于接收迭代器类型
template<class T>
class iterator_traits
{//迭代器中内嵌的类型是什么，萃取出来的就是什么类型
    typedef T::value_type value_type;
    /*  */
};
//特化版本，用于接收原生指针
template<class T>//原生指针会优先和特化版本匹配并实例化，如int*
class iterator_traits<T*>
{
    typedef T value_type;//这里value_type被定义为int，可以通过算法中的T::value_type temp;
    //不再报错，并且类型为我们想要的int
    /*  */
};

//回到算法设计上
template<class T>
typename iterator_traits<T>::value_type _stl_printf5(T Iter)
{
    iterator_traits<T>::value_type temp;
    /*  */
}
/*
添加模板特化和traits萃取，此时算法已经兼容了原生指针，传入一个迭代器或者原生指针
当需要创建变量或者作为返回值时，通过iterator_traits<T>::value_type即可
成功识别我们期待的类型，并发挥作用
*/